/***********************************************************************

	This file is part of KEEL-software, the Data Mining tool for regression, 
	classification, clustering, pattern mining and so on.

	Copyright (C) 2004-2010
	
	F. Herrera (herrera@decsai.ugr.es)
    L. Sánchez (luciano@uniovi.es)
    J. Alcalá-Fdez (jalcala@decsai.ugr.es)
    S. García (sglopez@ujaen.es)
    A. Fernández (alberto.fernandez@ujaen.es)
    J. Luengo (julianlm@decsai.ugr.es)

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see http://www.gnu.org/licenses/
  
**********************************************************************/

package keel.Algorithms.Neural_Networks.NNEP_Common;


import javolution.xml.XmlElement;
import javolution.xml.XmlFormat;
import keel.Algorithms.Neural_Networks.NNEP_Common.neuralnet.INeuralNet;
import net.sf.jclec.IFitness;
import net.sf.jclec.IIndividual;
import net.sf.jclec.base.AbstractIndividual;
import net.sf.jclec.fitness.SimpleValueFitness;


/**
 * <p>Individuals with a INeuralNet as genotype
 * @author Written by Pedro Antonio Gutierrez Penia (University of Cordoba) 16/7/2007
 * @author Written by Aaron Ruiz Mora (University of Cordoba) 16/7/2007
 * @version 0.1
 * @since JDK1.5
 * </p>
 */

public class NeuralNetIndividual extends AbstractIndividual<INeuralNet> {
	
	/**
	 * <p>
	 * Individuals with a INeuralNet as genotype
	 * <p>
	 */
	
    /////////////////////////////////////////////////////////////////
    // ------------------------------------- Marshal/unmarshal format
    /////////////////////////////////////////////////////////////////

	/**
	 * 
	 * Marshal individual fitness (inherited format). Then individual
	 * genotype.
	 * 
	 */
	
	protected static final javolution.xml.XmlFormat<NeuralNetIndividual> XML = 
		new XmlFormat<NeuralNetIndividual>(NeuralNetIndividual.class) 
		{
			public void format(NeuralNetIndividual source, XmlElement xml) 
			{
				// Call super format
				AbstractIndividual.XML.format(source, xml);
				// Marshal genotype
				xml.add(source.genotype, "genotype");
			}

			public NeuralNetIndividual parse(XmlElement xml)
			{
				// Resulting object
				NeuralNetIndividual result = 
					(NeuralNetIndividual) AbstractIndividual.XML.parse(xml);				
				// Unmarshal genotype
				result.genotype = xml.<INeuralNet>get("genotype");
				// Return result
				return result;
			}

			public String defaultName() 
			{
				return "neural-net-individual";
			}
		};
    
	/////////////////////////////////////////////////////////////////
	// --------------------------------------- Serialization constant
	/////////////////////////////////////////////////////////////////
	
	/** Generated by Eclipse */
	
	private static final long serialVersionUID = -2245049003640033592L;
	
	////////////////////////////////////////////////////////////////////
	// ----------------------------------------------------- Constructor
	////////////////////////////////////////////////////////////////////

	/**
	 * <p>
	 * Empty contructor
	 * </p>
	 */
	 
	public NeuralNetIndividual() 
	{
		super();
	}
	
	/**
	 * <p>
	 * Constructor that sets individual genotype
	 * 
	 * @param genotype Individual genotype
	 * </p>
	 */
	 
	public NeuralNetIndividual(INeuralNet genotype) 
	{
		super(genotype);
	}
	
	/**
	 * <p>
	 * Constructor that sets individual genotype and fitness
	 * 
	 * @param genotype Individual genotype
	 * @param fitness Individual fitness
	 * </p>
	 */
	
	public NeuralNetIndividual(INeuralNet genotype, IFitness fitness) 
	{
		super(genotype, fitness);
	}
	
	/////////////////////////////////////////////////////////////////
	// ----------- Overwriting AbstractIndividual<INeuralNet> methods
	/////////////////////////////////////////////////////////////////

	/**
	 * <p>
	 * Copies individuals
	 * @return A copy of the individual
	 * </p>
	 */
	public IIndividual copy() 
	{
		// Create new individuals, then return it
		if (fitness != null) {
			return new NeuralNetIndividual(this.genotype.copy(), fitness.copy());			
		}
		else {
			return new NeuralNetIndividual(this.genotype.copy());			
		}
	}
	
	/**
	 * <p>
	 * Hamming distance
	 * 
         * @param other other individual to compute the distance with.
	 * @return double Hamming distance between genotypes
	 * </p>
	 */
	 
	public double distance(IIndividual other)
	{
	    //TODO
	    return 0.;
	}

	/////////////////////////////////////////////////////////////////
	// ------------------------- Overwriting java.lang.Object methods
	/////////////////////////////////////////////////////////////////

	/**
	 * <p>
	 * Compares individuals
	 * @param other Individual
	 * @exception IllegalArgumentException if other isn't an instance 
	 *            of BinArrayIndividual
	 * @return True if the individuals are equals
	 * </p>           
	 */
	 
	public boolean equals(Object other) 
	{
		try {
			NeuralNetIndividual o = (NeuralNetIndividual) other;
			if (!this.genotype.equals(o.genotype))
				return false;
			return true;
		}
		catch(ClassCastException e) {
			throw new IllegalArgumentException
				("\"NeuralNetIndividual\" expected");
		}

	}
	
	/////////////////////////////////////////////////////////////////
	// ----------------------------------- Overwriting Object methods
	/////////////////////////////////////////////////////////////////
	
	/**
	 * <p>
	 * Converts a individual to string
	 * @return String with the individuals data
	 * </p>
	 */
	
	public String toString() 
	{
		StringBuffer sb = new StringBuffer();
		sb.append(renderNeuralNetIndividual());
		return sb.toString();
	}
		
	////////////////////////////////////////////////////////////////////
	// ----------------------------------------------- Protected methods
	////////////////////////////////////////////////////////////////////	
	
	/**
	 * <p>
	 * Returns a string that represents the individual
	 * This method can be used by class that extends NeuralNetIndividual
	 *
	 * @return String that represents individual
	 * </p>
	 */
	
	protected String renderNeuralNetIndividual() 
	{
		StringBuffer sb = new StringBuffer();
		sb.append(genotype);
		if(fitness!=null)
			sb.append("Fitness: " + ((SimpleValueFitness)fitness).getValue());
		else
			sb.append("Null Fitness");
		return sb.toString();	
	}

}

